package com.example.camunda.rest;

import cn.hutool.core.io.IoUtil;
import com.example.camunda.dto.DecisionDefinitionDto;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import org.camunda.bpm.engine.RepositoryService;
import org.camunda.bpm.engine.RuntimeService;
import org.camunda.bpm.engine.repository.DecisionDefinition;
import org.camunda.bpm.engine.repository.DecisionDefinitionQuery;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 决策定义
 *
 * @author heshao
 * @date 2021/11/8 17:25
 **/
@Api(tags = "决策定义")
@RestController
@RequestMapping("/decision-definition")
public class DecisionDefinitionController {

    private final RepositoryService repositoryService;
    private final RuntimeService runtimeService;

    public DecisionDefinitionController(RepositoryService repositoryService, RuntimeService runtimeService) {
        this.repositoryService = repositoryService;
        this.runtimeService = runtimeService;
    }

    /**
     * 查询所有决策定义
     *
     * @param pageNum  分页页码
     * @param pageSize 分页大小
     * @return
     */
    @GetMapping
    @ApiOperation("查询决策定义")
    public Page<DecisionDefinitionDto> list(@RequestParam(defaultValue = "0") Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize) {
        DecisionDefinitionQuery query = repositoryService.createDecisionDefinitionQuery().latestVersion();
        long count = query.count();
        List<DecisionDefinition> list = query.listPage(pageNum * pageSize, pageSize);
        List<DecisionDefinitionDto> dtoList = list.stream().map(DecisionDefinitionDto::from).collect(Collectors.toList());
        return new PageImpl<>(dtoList, PageRequest.of(pageNum, pageSize), count);
    }

    /**
     * 查询决策定义
     *
     * @param id 决策定义ID
     * @return
     */
    @GetMapping("/{id}")
    @ApiOperation("查询决策定义")
    public DecisionDefinitionDto get(@PathVariable String id) {
        DecisionDefinition decisionDefinition = repositoryService.getDecisionDefinition(id);
        return DecisionDefinitionDto.from(decisionDefinition);
    }

    /**
     * 删除决策定义
     *
     * @param id 决策定义ID
     * @return
     */
    @DeleteMapping("/{id}")
    @ApiOperation("删除决策定义")
    public void delete(@PathVariable String id) {
        repositoryService.deleteProcessDefinition(id);
    }

    /**
     * 查询流程图
     *
     * @param id 决策定义ID
     * @return
     */
    @GetMapping("/{id}/diagram")
    @ApiOperation("查询流程图")
    public void getDiagram(@PathVariable String id, HttpServletResponse response) {
        InputStream inputStream = repositoryService.getProcessDiagram(id);
        if (inputStream == null) {
            return;
        }
        DecisionDefinition decisionDefinition = repositoryService.getDecisionDefinition(id);
        getDiagram(response, inputStream, decisionDefinition.getDiagramResourceName());
    }

    /**
     * 查询流程图xml
     *
     * @param id 决策定义ID
     * @return
     */
    @GetMapping("/{id}/xml")
    @ApiOperation("查询流程图xml")
    public String getBpmn20Xml(@PathVariable String id) {
        InputStream in = repositoryService.getDecisionModel(id);
        return IoUtil.read(in, "UTF-8");
    }

    /**
     * 查询决策定义
     *
     * @param key 决策定义key
     * @return
     */
    @GetMapping("/key/{key}")
    @ApiOperation("查询决策定义")
    public DecisionDefinitionDto getByKey(@PathVariable String key) {
        DecisionDefinition decisionDefinition = repositoryService.createDecisionDefinitionQuery()
                .decisionDefinitionKey(key)
                .withoutTenantId()
                .latestVersion()
                .singleResult();
        return DecisionDefinitionDto.from(decisionDefinition);
    }

    /**
     * 删除决策定义
     *
     * @param key 决策定义key
     * @return
     */
    @DeleteMapping("/key/{key}")
    @ApiOperation("删除决策定义")
    public void deleteByKey(@PathVariable String key) {
        repositoryService.deleteProcessDefinitions().byKey(key).delete();
    }

    /**
     * 查询流程图
     *
     * @param key 决策定义key
     * @return
     */
    @GetMapping("/key/{key}/diagram")
    @ApiOperation("查询流程图")
    public void getDiagramByKey(@PathVariable String key, HttpServletResponse response) {
        DecisionDefinition decisionDefinition = repositoryService.createDecisionDefinitionQuery()
                .decisionDefinitionKey(key)
                .withoutTenantId()
                .latestVersion()
                .singleResult();
        InputStream inputStream = repositoryService.getDecisionDiagram(decisionDefinition.getId());
        if (inputStream == null) {
            return;
        }
        getDiagram(response, inputStream, decisionDefinition.getDiagramResourceName());
    }

    /**
     * 查询流程图xml
     *
     * @param key 决策定义key
     * @return
     */
    @GetMapping("/key/{key}/xml")
    @ApiOperation("查询流程图xml")
    public String getBpmn20XmlByKey(@PathVariable String key) {
        DecisionDefinition definition = repositoryService.createDecisionDefinitionQuery()
                .decisionDefinitionKey(key)
                .withoutTenantId()
                .latestVersion()
                .singleResult();
        InputStream in = repositoryService.getDecisionModel(definition.getId());
        return IoUtil.read(in, "UTF-8");
    }

    @SneakyThrows
    private void getDiagram(HttpServletResponse response, InputStream in, String filename) {
        response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");

        OutputStream out = response.getOutputStream();
        IoUtil.copy(in, out);

        IoUtil.close(in);

        IoUtil.flush(out);
        IoUtil.close(out);
    }


}
